package org.juiceshop.gm;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Chord extends MusicContainer {
	
	private static Map<String,int[]> _register;
	
	static {
		 _register = new HashMap<String, int[]>();
		 register("maj",4,7);
		 register("min",3,7);
		 register("aug",4,8);
		 register("dim",3,6);
		 register("maj7",4,7,11);
		 register("dom7",4,7,10);
	}
	
	public static void register(String name, int ...intervals) {
		_register.put(name, intervals);
	}
	
	public static int[] getPattern(String name) {
		if (! existPattern(name)) {
			throw new IllegalArgumentException("Unknown chord pattern '"+name+"'");
		}
		return _register.get(name);
	}

	static boolean existPattern (String name) {
		return _register.containsKey(name);
	}
		
	/**
	 * Returns all registered chord pattern names. 
	 * @return Pattern names as an unmodifiable set of strings.
	 */
	static Set<String> getRegisteredPatterns() {
		return Collections.unmodifiableSet(_register.keySet());
	}
		
	
	private static String K_ARPEGGIO;
	
	
	public Chord(Note note) {
		add(note);
	}
	 
	public Chord(Note note, String name) {
		this(note,getPattern(name));
	}

	public Chord(Note note, MusicObject... more) {
		add(note);
		for (MusicObject obj : more) {
			add(obj);
		}
	}

	public Chord(Note note, int... numbers) {
		this(note);
		for (int n : numbers) {
			add(n);
		}
	}
		
	
	public double getArpeggio() {
		return get(K_ARPEGGIO,0d);
	}
	
	public void setArpeggio(double arpeggio) {
		set(K_ARPEGGIO,arpeggio);
	}
	
	public Note getBaseNote() {
		return (Note) get(0);
	}

	@Override
	public double getValue() {
		return getBaseNote().getValue();
	}

	public Chord mod(Note note) {
		Chord copy = copy();
		copy.add(note);
		return copy;
	}

	public Chord mod(int n) {
		Chord copy = copy();
		copy.add(n);
		return copy;
	}

	public Chord mod(Phrase phr) {
		Chord copy = copy();
		copy.add(phr);
		return copy;
	}

	@Override
	public Phrase or(MusicObject obj) {
		return new Phrase(this).append(obj);
	}
	

	public void add(int steps) {
		add(getBaseNote().step(steps));
	}
	
	@Override
	public Chord copy() {
		return (Chord)super.copy();
	}
		
	@Override
	public String toString() {
		return toString('%');
	}

}
